<?php

// Fault.php
// Michael Baker
// 2010.06.21
// 
// implements network fault objects

if ( !defined( "IN_MDM" ) )
  exit;
  
class Fault
{
  private $id;         // corresponds to fault_id in Threshold table
  private $title;      // fault title as displayed in status output  
  private $callback;
  private $numerics;   // fault numerics
  private $extras;     // fault extras
  private $colorcodes; // fault colorcodes
  private $parent;     // parent nodecouple
  
  public function __construct( $callback, $parent )
  {
    $this->callback = $callback;
    $this->parent = $parent;
  }

  public function process( $qdb, $timestamp_pair )
  {
    // Process the timestamp query. After this function is
    // executed, external code expects the Fault to yield
    // NUMERICS, EXTRAS, and COLORCODES.
    
    global $dbase;
    
    $callback  = $this->callback;
    $couple    = $this->parent;
    
    $info      = $callback( $couple, $qdb, $timestamp_pair );
    
    $this->numerics   = $info[ 0 ];
    $this->extras     = $info[ 1 ];
    
    // Process colorcodes via numerics here
    $couple = $this->parent;
    $couple_id = $couple->get_id();
    
    $cat_id = $dbase->get_thresholding_category( $couple_id );
    $cc_rx  = $dbase->perform_thresholding( $cat_id, $this->id, $this->numerics[ 0 ] );
    $cc_tx  = $dbase->perform_thresholding( $cat_id, $this->id, $this->numerics[ 1 ] );
    
    // Assign colorcodes
    $this->colorcodes = array( $cc_rx, $cc_tx );
  }
  
  public function get_colorcodes()    { return $this->colorcodes;           }
  public function get_id()            { return $this->id;                   }
  public function set_id( $id )       { $this->id = $id;                    }
  public function get_title()         { return $this->title;                }
  public function set_title( $title ) { $this->title = $title;              }
  public function get_extras()        { return $this->extras;               }
  // public function get_sample_count()  { return $this->extras[ "ROWCOUNT" ]; }
  public function get_numerics()      { return $this->numerics;             }
}

function get_worst_color( $int_arr )
{
  // assuming higher colorcodes correspond to worse network states,
  // calculate the "worst" colorcode in an array
  
  if ( !count( $int_arr ) )
    return COLOR_EMPTYARR;
  
  $tmp = $int_arr[ 0 ];
  foreach ( $int_arr as $i ) if ( $i > $tmp ) $tmp = $i;
  return $tmp;
}

function f_loss( $nodecouple, $qdb, $timestamp_pair )
{
  // Callback for LOSS fault
  
  // Retrieve the node and timestamp clauses to go in the query
  $time_clause = get_tclause( $timestamp_pair[ 0 ], $timestamp_pair[ 1 ] );
  $date_array  = get_ymd_array( $timestamp_pair[ 0 ], $timestamp_pair[ 1 ] );
    
  // Get node objects from the nodecouple we're working with
  $nodes = $nodecouple->get_nodes();
  $init_node = $nodes[ 0 ];
  $fin_node = $nodes[ 1 ];
  
  // Fetch their OWAMP IDs
  $init_owamp = $qdb->get_node_owamp_id( $init_node->get_address() );
  $fin_owamp  = $qdb->get_node_owamp_id( $fin_node->get_address() );
  
  // use these OWAMP IDs to generate couple clauses for the SQL query
  $node_clause1 = $qdb->get_couple_clause( $init_owamp, $fin_owamp ); // i2f
  $node_clause2 = $qdb->get_couple_clause( $fin_owamp, $init_owamp ); // f2i
  
  // Initialize numerics and extras
  $numerics = array( NUM_DEFAULT, NUM_DEFAULT );
  $extras = array();
  $extras[ "OVERALL" ] = array( 0, 0 );
 
  // We must run two queries:
  // MAX(lost) rightward, and MAX(lost) leftward
  $query  = "(SELECT lost FROM %DATE%_" . QDB_TBL_DATA;
  $query .= " WHERE $time_clause AND $node_clause2)";
  $query2 = formulate_union( $query, "%DATE%", $date_array );
  $query3 = $query2 . " ORDER BY lost DESC LIMIT 1";
  
  $qdb->execute( $query3 );
  if ( $qdb->numrows() )
  {
    $row = $qdb->fetchone();
    $numerics[ 0 ] = $row[ 0 ];
  }
  else {
    error_log( "No rows returned for LOSS_LEFT query" );
  }
  
  $query  = "(SELECT lost FROM %DATE%_" . QDB_TBL_DATA;
  $query .= " WHERE $time_clause AND $node_clause1)";
  $query2 = formulate_union( $query, "%DATE%", $date_array );
  $query3 =  $query2 . " ORDER BY lost DESC LIMIT 1";
  
  $qdb->execute( $query3 );
  if ( $qdb->numrows() )
  {
    $row = $qdb->fetchone();
    $numerics[ 1 ] = $row[ 0 ]; 
  }
  else
  {
    error_log( "No rows returned for LOSS_RIGHT query" );
  }
  
  // Resolve the extras
  $query  = "(SELECT lost FROM %DATE%_" . QDB_TBL_DATA;
  $query .= " WHERE $time_clause AND $node_clause2)";
  $query2 = formulate_union( $query, "%DATE%", $date_array, 1 );
  $qdb->execute( $query2 );
  if ( $qdb->numrows() )
  {
    $resultset = $qdb->fetchall();
    
    foreach ( $resultset as $row )
    {
      $extras[ "OVERALL" ][ 0 ] += $row[ 0 ];
    }
    
  }
  else
  {
    error_log( "No rows returned for LOSS_S_LEFT query" );
  }
  
  $query  = "(SELECT lost FROM %DATE%_" . QDB_TBL_DATA;
  $query .= " WHERE $time_clause AND $node_clause1)";
  $query2 = formulate_union( $query, "%DATE%", $date_array, 1 );
  $qdb->execute( $query2 );
  if ( $qdb->numrows() )
  {
    $resultset = $qdb->fetchall();
    
    foreach ( $resultset as $row )
      $extras[ "OVERALL" ][ 1 ] += $row[ 0 ]; 
  }
  else
  {
    error_log( "No rows returned for LOSS_S_RIGHT query" );
  }

  $info = array( $numerics, $extras );
  return $info;
}

function f_delay( $nodecouple, $qdb, $timestamp_pair )
{
  // Callback for DELAY fault
  
  // Retrieve the node and timestamp clauses to go in the query
  $time_clause = get_tclause( $timestamp_pair[ 0 ], $timestamp_pair[ 1 ] );
  $date_array  = get_ymd_array( $timestamp_pair[ 0 ], $timestamp_pair[ 1 ] );
  
  // Get node objects from the nodecouple we're working with
  $nodes = $nodecouple->get_nodes();
  $init_node = $nodes[ 0 ];
  $fin_node  = $nodes[ 1 ];
  
  // Fetch their OWAMP IDs
  $init_owamp = $qdb->get_node_owamp_id( $init_node->get_address() );
  $fin_owamp  = $qdb->get_node_owamp_id( $fin_node->get_address() );
  
  // use these OWAMP IDs to generate couple clauses for the SQL query
  $node_clause1 = $qdb->get_couple_clause( $init_owamp, $fin_owamp ); // i2f
  $node_clause2 = $qdb->get_couple_clause( $fin_owamp, $init_owamp ); // f2i
  
  // Initialize numerics and extras
  $numerics = array( NUM_DEFAULT, NUM_DEFAULT );
  $extras   = array();
  $extras["OVERALL"] = array( 0, 0 );
  
  // We must run two queries:
  // MAX(ABS(max-min)) rightward, MAX(ABS(max-min)) leftward
  $query  = "(SELECT ABS(max-min) a FROM %DATE%_" . QDB_TBL_DATA;
  $query .= " WHERE $time_clause AND $node_clause2)";
  $query2 = formulate_union( $query, "%DATE%", $date_array );
  $query3 = $query2 . " ORDER BY a DESC LIMIT 1";
  
  $qdb->execute( $query3 );
  
  if ( $qdb->numrows() )
  {
    $row = $qdb->fetchone();
    $numerics[ 0 ] = $row[ 0 ];
  }
  
  $query  = "(SELECT ABS(max-min) a FROM %DATE%_" . QDB_TBL_DATA;
  $query .= " WHERE $time_clause AND $node_clause1)";
  $query2 = formulate_union( $query, "%DATE%", $date_array );
  $query3 = $query2 . " ORDER BY a DESC LIMIT 1";
  $qdb->execute( $query3 );
  if ( $qdb->numrows() )
  {
    $row = $qdb->fetchone();
    $numerics[ 1 ] = $row[ 0 ];
  }
  
  // Resolve the extras
  $query  = "(SELECT max a FROM %DATE%_" . QDB_TBL_DATA;
  $query .= " WHERE $time_clause AND $node_clause2)";
  $query2 = formulate_union( $query, "%DATE%", $date_array );
  $query3 = $query2 . " ORDER BY a DESC LIMIT 1";
  
  $qdb->execute( $query3 );
  
  if ( $qdb->numrows() ) {
    $row = $qdb->fetchone();
    $extras[ "OVERALL" ][ 0 ] = $row[ 0 ];
  }
  
  $query  = "(SELECT max a FROM %DATE%_" . QDB_TBL_DATA;
  $query .= " WHERE $time_clause AND $node_clause1)";
  $query2 = formulate_union( $query, "%DATE%", $date_array );
  $query3 = $query2 . " ORDER BY a DESC LIMIT 1";
  
  $qdb->execute( $query3 );
  
  if ( $qdb->numrows() ) {
    $row = $qdb->fetchone();
    $extras[ "OVERALL" ][ 1 ] = $row[ 0 ];
  }
  
  $info = array( $numerics, $extras );
  return $info;
}

// PDV fault callbacks - left for later
function f_pdv( $nodecouple, $qdb, $timestamp_pair ) { }

?>